
import java.io.*;
import java.util.*;

import cii_lib.CIIdata;

import gnu.io.RXTXCommDriver;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
  
public class USBCii implements Runnable, SerialPortEventListener  {

	InputStream inputStream;
	OutputStream outputStream;
	Thread readThread;
	static String TimeStamp;
	String divertCode = "10";
	String feedBackDataCmp = new String();
	
	SerialPort sPort = null;
	CommPortIdentifier portID;
	
	public void init () {
		try {
			//printPorts();
			
			portID = CommPortIdentifier.getPortIdentifier("COM2");
			try {
			sPort=(SerialPort) portID.open("TEST",100);
			} catch(PortInUseException pe) {
				System.out.println("Port in use");
			}
			System.out.println(sPort.getDataBits());
			System.out.println(portID.getName());
		} catch (Exception e) {
			System.out.println(e);
			printPorts();
			//
		}
	}
	
	public static void main(String[] args) {
		USBCii usb = new USBCii();		
	}
	
	public USBCii () {
		init();
		try {
			sPort.addEventListener(this);
			} catch (TooManyListenersException e) {}
			sPort.notifyOnDataAvailable(true);
		useComm(sPort);
		try {
			outputStream = (OutputStream)sPort.getOutputStream();
			//writePort(0);writePort(0);
			//writeUSB(1, new CIIdata(16,7));
			//readUSB(1);
//			String tmp = new String("00000001");
//			System.out.println("writing byteS: " + tmp.getBytes());
//			outputStream.write(tmp.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void useComm(SerialPort sp) {
		try {
		inputStream = (InputStream)sp.getInputStream();
		} catch(Exception e) {
			System.out.println(e);
		}
		System.out.println("got inputstrem");
		System.out.println(new String(divertCode.getBytes()));
			try {

			sp.setSerialPortParams(9600,
			SerialPort.DATABITS_8,
			SerialPort.STOPBITS_1, 
			SerialPort.PARITY_NONE);

			sp.setDTR(false);
			sp.setRTS(false);
			sp.notifyOnOutputEmpty(true);

			} catch (UnsupportedCommOperationException e) {}

			readThread = new Thread(this);
			readThread.start();
	}
	
	public void printPorts() {
		CommPortIdentifier port2;
		Enumeration portList = CommPortIdentifier.getPortIdentifiers();
		for (int i=0;portList.hasMoreElements();i++) {
			port2 = (CommPortIdentifier)portList.nextElement();
			if (port2.getPortType() == CommPortIdentifier.PORT_SERIAL)  
				System.out.println("\n"+i+" " + port2.getName()); 
				
			}
	}
	
	public String fullBitString(String in, int size) {
		String tmp = new String();
		if (in.length()<size) //TODO obsluga bledu
			for(int i=0;i<size-in.length();i++)
				tmp = tmp+ "0";		
		return tmp.concat(in);
	}
	
	public int writeUSB(long adres, CIIdata data) {
		System.out.println("\t\tWRItE !");
			Long tma = new Long(adres);
			int l_beg=0, it=0;
			String adr16= fullBitString(Long.toBinaryString(adres),16);
			for (int l=l_beg+4-1;l>=l_beg;l--) {
				String licznik = new String(fullBitString(Integer.toBinaryString(it),4));
				String wartosc = new String(adr16.substring((l*4), ((l+1)*4)));
				//System.out.println(adr16.substring((l*4), ((l+1)*4)));
				writePort(Integer.parseInt(licznik+wartosc,2));
				System.out.println("l:"+licznik+":"+wartosc + " | " + Integer.parseInt(licznik+wartosc,2));
				it++;
			}
			it=0;
			String dana = new String(fullBitString(data.GetBin(),16));
			for (int l=l_beg+4-1;l>=l_beg;l--) {
				String licznik = new String(fullBitString(Integer.toBinaryString(it+4),4));
				String wartosc = new String(dana.substring((l*4), ((l+1)*4)));
				//System.out.println(adr16.substring((l*4), ((l+1)*4)));
				writePort(Integer.parseInt(licznik+wartosc,2));
				System.out.println("l:"+licznik+":"+wartosc + " | " + Integer.parseInt(licznik+wartosc,2));
				it++;
			}
			feedBackDataCmp = adr16 + dana;
			System.out.println(feedBackDataCmp);
		return 0;
	}
	
	public long readUSB(long adres) {
		System.out.println("\t\tREaD !");
			int l_beg=8;
			String adr16= fullBitString(Long.toBinaryString(adres),16);
			for (int l=3;l>=0;l--) {
				String licznik = new String(fullBitString(Integer.toBinaryString(l_beg),4));
				//String wartosc = new String(adr16.substring((l-l_beg)*4, (((l-l_beg)+1)*4)));
				String wartosc = new String(adr16.substring((l*4), ((l+1)*4)));
				//System.out.println(adr16.substring((l*4), ((l+1)*4)));
				writePort(Integer.parseInt(licznik+wartosc,2));
				System.out.println("Rd l:"+licznik+":"+wartosc + " | " + Integer.parseInt(licznik+wartosc,2));
				l_beg++;
			}
			for (int l=l_beg;l<l_beg+4;l++) {
				String licznik = new String(fullBitString(Integer.toBinaryString(l),4));
				String wartosc = new String("0000");
				//System.out.println(adr16.substring((l*4), ((l+1)*4)));
				writePort(Integer.parseInt(licznik+wartosc,2));
				System.out.println("Rd l:"+licznik+":"+wartosc + " | " + Integer.parseInt(licznik+wartosc,2));
			}
			
		return 0;
	}
	
	public int writePort(int b) {
//		for(int a=0;a<199999999;a++); 
		try {outputStream.write(b); } 
		catch (Exception e) {
			System.out.println("Writing " +b+" to port failed:");
			e.printStackTrace();
		}
		return 0;
	}
	
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("running");
		try {
			Thread.sleep(100);
			} catch (InterruptedException e) {}
		
	}

	public synchronized void serialEvent(SerialPortEvent event) {
		// TODO Auto-generated method stub
		switch(event.getEventType()) {
			case SerialPortEvent.BI:
			case SerialPortEvent.OE:
			case SerialPortEvent.FE:
			case SerialPortEvent.PE:
			case SerialPortEvent.CD:
			case SerialPortEvent.CTS:
			case SerialPortEvent.DSR:
			case SerialPortEvent.RI:
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
				System.out.println("\nempty:");
				break;
			case SerialPortEvent.DATA_AVAILABLE:
				System.out.println("heeere");
				for(int a=0;a<199999999;a++); 
				StringBuffer readBuffer = new StringBuffer();
				int c;
				try {
					while (inputStream.available() > 0){
							//(c=inputStream.read()) != 10)
						c=inputStream.read();
						System.out.println("\tRead: "+fullBitString(Integer.toBinaryString(c),8));
						readBuffer.append((char) c);
					}
					String scannedInput = readBuffer.toString();
					TimeStamp = new java.util.Date().toString();
					System.out.println(TimeStamp + ": scanned input received:" + scannedInput);
					inputStream.close();
					
//						if(scannedInput.substring(0,1).equals("F")){
//							outputStream = sPort.getOutputStream();
//							outputStream.write(divertCode.getBytes());
//							System.out.println(TimeStamp + ": diverter fired");
//							outputStream.close();
//						} else {
//							System.out.println(TimeStamp + ": diverter not diverted");
//						}
				} catch (IOException e) {}
//				byte[] readBuffer = new byte[8];
//				System.out.println("reading:");
//				TimeStamp = new java.util.Date().toString();
//				String readed = "null";
//			    int numBytes=0;  
//					try {
//			        while (inputStream.available() > 0) {
//			          numBytes = inputStream.read(readBuffer);
//			        }
//			        readed= (new String(readBuffer));
//			        System.out.println(TimeStamp + "["+numBytes +"] "+ readed);
//			        for (int i=0;i<numBytes;i++) System.out.print(" "+ readed.codePointAt(i));
//			      } catch (IOException e) {
//			      }
		break;
		}
	}
	
}

